from django.db.models import Q
from django import forms
from rest_framework.views import APIView
from app01.models import IDCDevice, Client, Cabinet, MachineRoom, IDCDeviceLog
from django.http import JsonResponse, HttpResponse
from django.core.exceptions import ValidationError
from app01.Baseview import BasedAPIView
from .devchangelog import log_device_action



class DeviceForm(forms.ModelForm):
    class Meta:
        model = IDCDevice
        fields = '__all__'

    # def __init__(self, *args, **kwargs):
    #     super(DeviceForm, self).__init__(*args, **kwargs)
    #     if 'instance' in kwargs:
    #         instance = kwargs['instance']
    #         if instance and instance.room:
    #             self.fields['cabinet'].queryset = Cabinet.objects.filter(machine_room=instance.room)
    #         else:
    #             self.fields['cabinet'].queryset = Cabinet.objects.none()
    #
    # def clean_client(self):
    #     client = self.cleaned_data.get('client')
    #     if client is None or not Client.objects.filter(id=client.pk).exists():
    #         raise forms.ValidationError(["指定的客户端不存在"])
    #     return client
    #
    # def clean_cabinet(self):
    #     cabinet = self.cleaned_data.get('cabinet')
    #     if cabinet is None or not Cabinet.objects.filter(id=cabinet.pk).exists():
    #         raise forms.ValidationError(["指定的机柜不存在"])
    #     return cabinet
    #
    # def clean_room(self):
    #     room = self.cleaned_data.get('room')
    #     if room is None or not MachineRoom.objects.filter(id=room.pk).exists():
    #         raise ValidationError("指定的机房不存在")
    #     return room


class DeviceListView(BasedAPIView):
    def get(self, request, *args, **kwargs):
        module = kwargs.get('module')
        if module == 'get_device_all':
            return self.get_device_all(request)
        if module == 'get_options':
            return self.get_options(request)

    def post(self, request, *args, **kwargs):
        module = kwargs.get('module')
        if module == 'add':
            return self.add(request)
        if module == 'edit':
            return self.edit(request)
        if module == 'dele':
            return self.dele(request)

    def get_device_all(self, request):
        # params = {
        #     'page': int(request.GET.get('page', 1)),
        #     'pagesize': int(request.GET.get('pagesize', 10)),
        #     'device_type': request.GET.get('device_type', None),
        #     'brand': request.GET.get('brand', None),
        #     'model': request.GET.get('model', None),
        #     'status': request.GET.get('status', None),
        #     'machine_room': request.GET.get('machine_room', None),
        #     'cabinet': request.GET.get('cabinet', None),
        #     'client': request.GET.get('client', None),
        # }
        page = int(request.GET.get('page', 1))
        pagesize = int(request.GET.get('pagesize', 10))
        device_type = request.GET.get('device_type', None)
        brand = request.GET.get('brand', None)
        model = request.GET.get('model', None)
        status = request.GET.get('status', None)
        machine_room = request.GET.get('room', None)
        cabinet = request.GET.get('cabinet', None)
        client = request.GET.get('client', None)

        query = Q()
        if device_type:
            query &= Q(device_type__icontains=device_type)
        if brand:
            query &= Q(brand__icontains=brand)
        if model:
            query &= Q(model__icontains=model)
        if status:
            query &= Q(status=status)
        if client:
            query &= Q(client__client_name__iexact=client)
        if machine_room:
            #query &= Q(room__room_name__iexact=machine_room) ###根据名称查询
            query &= Q(room=machine_room)  ###根据id查询
        if cabinet:
            query &= Q(cabinet__cabinet_number=cabinet)
        # 使用 select_related 和 prefetch_related 减少数据库查询次数
        devices = IDCDevice.objects.select_related('client').prefetch_related('cabinet__machine_room').filter(
            query).order_by('-id')
        total = devices.count()
        device_dic = []
        for device in devices:
            status_desc = dict(IDCDevice.STATUS_CHOICES).get(device.status, '')
            res_data = {
                'id': device.id,
                'device_type': device.device_type,
                'brand': device.brand,
                'model': device.model,
                'height': device.height,
                'sn': device.sn,
                'status': {
                    'id': device.status,
                    'value': status_desc
                },
                'notes': device.notes,
                'memory': device.memory,
                'disk': device.disk,
                'ipmi_ip': device.ipmi_ip,
                'main_ip': device.main_ip,
                'os_password': device.os_password,
                'vlan': device.vlan,
                'device_code': device.device_code,
                'ip_address': device.ip_address,
                'subnet': device.subnet,
                'gateway': device.gateway,
                'bound_mac': device.bound_mac,
                'datetime': device.UpdatedTime.strftime('%Y-%m-%d %H:%M:%S'),
                'client':
                    {
                        "id": device.client.id,
                        "name": device.client.client_name,
                        "abbr": device.client.client_abbreviation
                    },
                'cabinet': {
                    "id": device.cabinet.id,
                    "status": device.cabinet.status,
                    'name': device.cabinet.cabinet_number,
                },
                'room': {
                    'id': device.cabinet.machine_room.id,
                    "name": device.cabinet.machine_room.room_name,

                },

            }
            device_dic.append(res_data)
        start_page = page * pagesize - pagesize
        end_page = page * pagesize
        paginated_data = device_dic[start_page:end_page]

        clients = Client.objects.all()
        cabinets = Cabinet.objects.all()
        machine_rooms = MachineRoom.objects.all()
        ch_status = IDCDevice.STATUS_CHOICES

        options = {
            'clients': [
                {
                    'id': client.id,
                    'name': client.client_name,
                    'abbr': client.client_abbreviation
                }
                for client in clients
            ],
            'cabinets': [
                {
                    'id': cabinet.id,
                    'number': cabinet.cabinet_number,
                    "room_id": cabinet.machine_room.id,
                    'machine_room': cabinet.machine_room.room_name
                }
                for cabinet in cabinets
            ],
            'machine_rooms': [
                {
                    'id': room.id,
                    'name': room.room_name
                }
                for room in machine_rooms
            ],
            'status': [
                {
                    'id': idx,
                    'value': choice[0],
                    'label': choice[1]
                }
                for idx, choice in enumerate(ch_status)
            ]
        }
        data = {
            'total': total,
            'data': paginated_data,
            'options': options

        }
        return super().success(data=data)

    def add(self, request):
        data = request.data
        form = DeviceForm(data=data)

        if form.is_valid():
            device = form.save(commit=False)
            device.save(request=request)
            # 构建响应数据
            device_dic = {
                'id': device.id,
                'device_type': device.device_type,
                'brand': device.brand,
                'model': device.model,
                'height': device.height,
                'sn': device.sn,
                'status': device.status,
                'notes': device.notes,
                'memory': device.memory,
                'disk': device.disk,
                'ipmi_ip': device.ipmi_ip,
                'main_ip': device.main_ip,
                'os_password': device.os_password,
                'vlan': device.vlan,
                'device_code': device.device_code,
                'ip_address': device.ip_address,
                'subnet': device.subnet,
                'gateway': device.gateway,
                'bound_mac': device.bound_mac,
                'client_id': device.client.id,
                'cabinet_id': device.cabinet.id,
                'room_id': device.room.id,
            }
            # 返回成功响应
            return super().success(msg="新增成功", data=device_dic)
        else:
            errors = form.errors
            return super().error(msg=errors)

    def edit(self, request):
        '''编辑方法获取json数据'''
        data = request.data
        device_id = data.get('id')
        try:
            device = IDCDevice.objects.get(id=device_id)
        except IDCDevice.DoesNotExist:
            return super().error(msg="设备不存在")

        form = DeviceForm(data=data, instance=device)
        if form.is_valid():
            device = form.save(commit=False)
            device.save(request=request)
            device_dic = {  # 构建响应数据
                'id': device.id,
                'device_type': device.device_type,
                'brand': device.brand,
                'model': device.model,
                'height': device.height,
                'sn': device.sn,
                'status': device.status,
                'notes': device.notes,
                'memory': device.memory,
                'disk': device.disk,
                'ipmi_ip': device.ipmi_ip,
                'main_ip': device.main_ip,
                'os_password': device.os_password,
                'vlan': device.vlan,
                'device_code': device.device_code,
                'ip_address': device.ip_address,
                'subnet': device.subnet,
                'gateway': device.gateway,
                'bound_mac': device.bound_mac,
                'client': {
                    'id': device.client.id,
                    'name': device.client.client_name,
                    'name_abbr': device.client.client_abbreviation
                },
                'cabinet': {
                    'id': device.cabinet.id,
                    'name': device.cabinet.cabinet_number
                },
                'room': {
                    'id': device.room.id,
                    'name': device.room.room_name
                }
            }
            return super().success(msg="修改成功", data=device_dic)
        else:
            errors = form.errors
            return super().error(msg=errors)

    def dele(self, request):
        '''删除数据GET方法获取id'''
        ids = request.GET.get("id", "")
        if ids == "":
            return super().error(msg="ID不能为空")
        try:
            ids_int = [int(i) for i in ids.split(",") if i]
        except ValueError:
            return super().error(msg="ID格式错误，请输入数字")
        devices = IDCDevice.objects.filter(id__in=ids_int)
        if not devices.exists():
            return self.error(msg="数据不存在")
        devices.delete()
        return super().success(msg="删除成功")
